Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHPUnit 11.5.0 | AssertContainsOnly trait: polyfill the Assert::assertContains[Not]Only*() methods #225

Merged
merged 2 commits into from
Jan 8, 2025

Conversation

jrfnl
Copy link
Collaborator

@jrfnl jrfnl commented Jan 6, 2025

PHPUnit 11.5.0 introduced a range of new assertions. These assertions are specialized alternatives to the pre-existing assert[Not]ContainsOnly() methods, which are now soft deprecated and will be removed in PHPUnit 13.0.

This commit:

  • Adds two traits with the same name.
    One to polyfill the methods when not available in PHPUnit.
    The other to allow for use-ing the trait in PHPUnit versions in which the methods are already natively available.
  • Adds logic to the custom autoloader which will load the correct trait depending on the PHPUnit version used.
  • Adds tests.

Most polyfilled methods can just fall-through to the pre-existing methods as a polyfill.
The exceptions to this rule are:

  • assertContains[Not]OnlyIterable() which needs custom logic for PHPUnit < 7.1.0 in which the PHP native iterable type was not yet supported.
  • assertContains[Not]OnlyClosedResource() which needs custom logic for PHP < 7.2 in which the PHP native resource (closed) type did not exist yet.
    In this last case, the custom logic is used for the polyfill on all PHP versions as there is no functional check (in contrast to a version check) which can be used to determine whether the resource (closed) type is available.

All new methods are loosely tested.

Includes:

  • Adding information on the new polyfill to the README.
  • Adding the new polyfill to the existing TestCases classes.

Refs:

Fixes #214

…tContains[Not]Only*() methods

PHPUnit 11.5.0 introduced a range of new assertions. These assertions are specialized alternatives to the pre-existing `assert[Not]ContainsOnly()` methods, which are now soft deprecated and will be removed in PHPUnit 13.0.

This commit:
* Adds two traits with the same name.
    One to polyfill the methods when not available in PHPUnit.
    The other to allow for `use`-ing the trait in PHPUnit versions in which the methods are already natively available.
* Adds logic to the custom autoloader which will load the correct trait depending on the PHPUnit version used.
* Adds tests.

Most polyfilled methods can just fall-through to the pre-existing methods as a polyfill.
The exceptions to this rule are:
* `assertContains[Not]OnlyIterable()` which needs custom logic for PHPUnit < 7.1.0 in which the PHP native `iterable` type was not yet supported.
* `assertContains[Not]OnlyClosedResource()` which needs custom logic for PHP < 7.2 in which the PHP native `resource (closed)` type did not exist yet.
    In this last case, the custom logic is used for the polyfill on all PHP versions as there is no functional check (in contrast to a version check) which can be used to determine whether the `resource (closed)` type is available.

All new methods are loosely tested.

Includes:
* Adding information on the new polyfill to the README.
* Adding the new polyfill to the existing `TestCases` classes.

Refs:
* sebastianbergmann/phpunit@a726e03

Fixes 214
@coveralls
Copy link

coveralls commented Jan 6, 2025

Coverage Status

coverage: 97.912% (+0.4%) from 97.504%
when pulling 63a5798 on feature/214-support-phpunit-11.5.0
into 648f805 on 3.x.

*
* @return void
*/
final public static function assertContainsNotOnlyInstancesOf( string $type, $haystack, string $message = '' ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrfnl Refresh my memory please. Should the new polyfills add the string type declaration in the signature?

I'm asking because a lot of the polyfills do not (some do). Thanks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid question and the answer is "yes".

The reasoning for this is as follows:

  • General speaking the function signature for a polyfill should be the same as the signature in PHPUnit itself, providing the minimum PHP version of the PHPUnit Polyfill version allows for it.
    In this case, that means, the string type for $type and $message can be added, but the iterable type for $haystack cannot be added yet (needs PHP 7.1+, while the Polyfills 3.x series has a PHP 7.0 minimum).
  • For those types which cannot be added on introduction of polyfill functions, the Polyfills package follows PHPUnit itself.
    This means that missing types will be added to individual polyfills once the minimum PHPUnit version supported by the polyfill aligns with the PHPUnit version in which the types were added in PHPUnit itself (as at that point the minimum supported PHP version of the Polyfills package will also allow for adding those types).
    PHPUnit 7.0 introduces scalar types and return types to most assertions, so once the minimum supported PHPUnit version of the Polyfills is 7.0, the function signature of pre-existing polyfills will be updated to mirror the changes made in PHPUnit 7.0.
    Along the same lines, PHPUnit 8.0 added strict_types to PHPUnit itself. Once the Polyfills have a minimum of PHPUnit 8, this will be applied to the polyfills too.

Does that help and provide a clear enough guideline to follow for this ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, yes, makes sense. Thanks for sharing this information. I'll bookmark as a guideline.

README.md Outdated
| [`Assert::assertContainsOnlyClosedResource()`] * | [`Assert::assertContainsNotOnlyClosedResource()`] * |
| [`Assert::assertContainsOnlyScalar()`] | [`Assert::assertContainsNotOnlyScalar()`] |
| [`Assert::assertContainsOnlyString()`] | [`Assert::assertContainsNotOnlyString()`] |
| [`Assert::assertContainsNotOnlyInstancesOf()`] | |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though there's only the "Not" version, should this assert be listed in the "Not" (inverse) column for consistency?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point.

Makes me think I should probably reformat the table for the AssertIsType polyfills too.

Copy link
Collaborator Author

@jrfnl jrfnl Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - see: #226 #227

*
* @return void
*/
final public static function assertContainsNotOnlyInstancesOf( string $type, $haystack, string $message = '' ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why list assertContainsNotOnlyInstancesOf() first? In the Framework/Assert.php file, it's listed after assertContainsNotOnlyString(). Wondering if placement should match PHPUnit for comparison? What do you think @jrfnl?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't used the order in the Framework/Assert.php file as a guideline anywhere, though at times the assertion order may align, in which case it's more by accident than by design.

In this case, there are two - very arbitrary - reasons for the order:

  1. It was listed first in the changelog of PHPUnit 11.5.0 ;-)
  2. All the other assertions are basically sets of two assertions, while this is a single new assertion. Using some form of alphabetic ordering would bury the assertion in the middle of those sets making this "odd one out" hard to find. Which leaves having it either as the first or the last method in the class and I, arbitrarily, choose to place it as the first.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I too noticed it was listed first in the changelog. That's a good point.

I followed the PHPUnit file during the review, which caught my attention. Point 2 makes sense.

Thanks for sharing your reasons.

Copy link
Collaborator

@hellofromtonya hellofromtonya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Ready for merge.

@jrfnl jrfnl merged commit 0298bb3 into 3.x Jan 8, 2025
149 checks passed
@jrfnl jrfnl deleted the feature/214-support-phpunit-11.5.0 branch January 8, 2025 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle new assertions introduced in PHPUnit 11.5.0
3 participants